﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Xrm.Sdk;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Client;
using Microsoft.Xrm.Client.Services;
using Microsoft.Xrm.Sdk.Metadata;


///<Summary \>
/// 25 Marzo 2014 : Se solicitó cambiar Picklist de Bono KM por Número entero, se agrega valor de statuscode para liberar el Km.
/// Autor: Julio Esquivel
/// 7 Abril 2014: Se agregó código para considerar criterio del día del padre y día de la madre. 
/// Se agrega código para considerar socios corporativos. Se agrega código para considerar tipo de movimientos N:N.
/// 3 Noviembre 2014 - Regresamos Guid de Reg Creado, para ser Actualizado en Movimiento de Tipo Acreditación
/// 11 Diciembre 2014 - Agregamos código para no aplicar restricción de sólo un Ganador. Sólo en Acumulaciones - Origenes-Destinos
///<Summary \>


namespace GFA.SP.Plugins
{
    public class Promociones
    {
        #region Variables Privadas

        private string _Usuario;
        private string _Contraseña;
        private string _Uri;
        private DateTime _Fecha;
        private DateTime _Fechacumple;
        private string _tiposocio;
        private string _tipomedio;
        private string _tipomovimiento;
        private string _socioid;
        private string _ciudadid;
        private string _OrigenDestinoid;
        private string _numerodeservicio;
        private bool _esmovacumulacion;

        private IOrganizationService _service;

        #endregion

        #region GET, SET Propiedades de la Clase

        public string Usuario
        {
            get { return _Usuario; }
            set { _Usuario = value; }
        }

        public string Contraseña
        {
            get { return _Contraseña; }
            set { _Contraseña = value; }
        }

        public string Uri
        {
            get { return _Uri; }
            set { _Uri = value; }
        }

        public DateTime Fecha
        {
            get { return _Fecha; }
            set { _Fecha = value; }
        }

        public string TipoSocio
        {
            get { return _tiposocio; }
            set { _tiposocio = value; }
        }

        public string TipoMedio
        {
            get { return _tipomedio; }
            set { _tipomedio = value; }
        }

        public string TipoMovimiento
        {
            get { return _tipomovimiento; }
            set { _tipomovimiento = value; }
        }

        public string Socioid
        {
            get { return _socioid; }
            set { _socioid = value; }
        }

        public string OrigenDestinoid
        {
            get { return _OrigenDestinoid; }
            set { _OrigenDestinoid = value; }
        }

        public string NumerodeServicio
        {
            get { return _numerodeservicio; }
            set { _numerodeservicio = value; }
        }
        // 11 Diciembre 2014 - Bandera para saber si es un mov de acumulacion
        public bool EsMovAcumulacion
        {
            get { return _esmovacumulacion; }
            set { _esmovacumulacion = value; }
        }

        #endregion

        #region Servicio CRM
        /// <summary>
        ///  Se crea una instancia de Servicio por defecto.
        /// </summary>
        public Promociones(IOrganizationService serv)
        {
            _service = serv;
        }

        #endregion


        /// <summary>
        ///  Método que revisa si aplica Promoción al movimiento que se está realizando
        /// </summary>
        public Guid RevisaPromocion()
        {

            #region Variables Locales
            bool AsignarPromocion = false;
            bool revisaganadores;
            int bonokm;
            int numganadores;
            int ganadoresactuales;
            string promocionid;
            bool criteriocumple;
            bool criterioddpadre;
            bool criterioddmadre;
            bool criterioorigendest;
            bool criteriociudad;
            bool criterionumservicio;
            string destinoid;
            string origendestid;
            string numeroservicio;
            DateTime vigenciaal;
            DateTime vigenciadel;
            string CveJustifica = "";
            bool tienehijos;
            int genero;
            string ClaveSocio;
            // 3 Noviembre 2014 - Ajuste Cancelaciones
            string NombrePromo = string.Empty;
            #endregion

            // 3 Nov 2014 - Regresamos Guid de Reg Creado
            Guid IdKmExtraProm = Guid.Empty;

            try
            {
                if (_socioid == string.Empty || _socioid == null)
                    throw new Exception("Se requiere el identificador del socio para validar las promociones");

                if (_tiposocio == string.Empty || _tiposocio == null)
                    throw new Exception("Se requiere el identificador del tipo de socio para validar las promociones");

                if (_tipomedio == string.Empty || _tipomedio == null)
                    throw new Exception("Se requiere el identificador del tipo de medio para validar las promociones");

                if (_tipomovimiento == string.Empty || _tipomedio == null)
                    throw new Exception("Se requiere el identificador del tipo del movimiento para validar las promociones");

                if (_Fecha == DateTime.MinValue)
                    _Fecha = DateTime.Now.ToLocalTime();

                #region Revisa tipo de promoción

                var columnprom = new[] { "gfa_tiposociosid", "gfa_id" };
                Entity TipoPromocion = _service.Retrieve("gfa_tiposocios", new Guid(_tiposocio), new ColumnSet(columnprom));
                ClaveSocio = ExisteAtributo("gfa_id", TipoPromocion) ? TipoPromocion["gfa_id"].ToString() : "";

                #endregion

                if (ClaveSocio.ToUpper() != "CO")
                {
                    #region Entidad Contact

                    var columnNames = new[] { "contactid", "birthdate", "gfa_ciudadid", "gendercode", "gfa_tienehijos" };
                    Entity Contacto = _service.Retrieve("contact", new Guid(_socioid), new ColumnSet(columnNames));
                    _ciudadid = ExisteAtributo("gfa_ciudadid", Contacto) ? ((EntityReference)Contacto["gfa_ciudadid"]).Id.ToString() : "";
                    _Fechacumple = ExisteAtributo("birthdate", Contacto) ? ((DateTime)Contacto["birthdate"]).ToLocalTime() : DateTime.MinValue;
                    tienehijos = ExisteAtributo("gfa_tienehijos", Contacto) ? (bool)Contacto["gfa_tienehijos"] : false;
                    genero = ExisteAtributo("gendercode", Contacto) ? ((OptionSetValue)Contacto["gendercode"]).Value : 0;
                    #endregion
                }
                else
                {
                    var columnscuenta = new[] { "accountid", "gfa_ciudadid" };
                    Entity cuenta = _service.Retrieve("account", new Guid(_socioid), new ColumnSet(columnscuenta));
                    _ciudadid = ExisteAtributo("gfa_ciudadid", cuenta) ? ((EntityReference)cuenta["gfa_ciudadid"]).Id.ToString() : "";
                    _Fechacumple = DateTime.MinValue;
                    tienehijos = false;
                    genero = -1;
                }

                #region Revisa Promociones
                string[] ColumSetPlantilla = new string[] { "gfa_promocionesid", "gfa_bonokm", "gfa_tipodesocioid","gfa_movimientoid","gfa_vigenciaal",
                                 "gfa_vigenciadel","gfa_medioid","gfa_ganadores","gfa_numganadores","gfa_conteoganadoresactuales","gfa_promocumple","gfa_ciudadid",
                                 "gfa_activacriterio","gfa_activacriterionumser","gfa_numerodeservicio","gfa_activacriterioorigendest","gfa_origendestinoid",
                                  "statecode","statuscode","gfa_promodiadelpadre","gfa_promodiadelasmadres", "gfa_name"};



                EntityCollection Promociones = RevisaPromociones("gfa_promociones", ColumSetPlantilla, _Fecha, "gfa_tipodesocioid", _tiposocio, "gfa_movimientoid", _tipomovimiento);


                /*******Justificación de la acumulación de Km extras.********/
                string[] ColumSetJust = new string[] { "gfa_justmovid", "gfa_id" };
                EntityCollection Justificacion = RecuperacionMultiple("gfa_justmov", ColumSetJust, "gfa_id", "KMP");
                foreach (Entity Just in Justificacion.Entities)
                {
                    CveJustifica = ExisteAtributo("gfa_justmovid", Just) ? Just["gfa_justmovid"].ToString() : "";
                }

                /*************************************************************/

                if (Promociones.Entities.Count == 0)
                    return Guid.Empty;  // 3 Nov 2014 - Regresamos Guid de Reg Creado

                string[] arraymvtos = new string[1];
                foreach (Entity Promocion in Promociones.Entities)
                {
                    #region #Valida Tipo de movimiento

                    /*Revisa si la promoción aplica pra el tipo de movimiento que se esta realizadndo*/
                    EntityCollection Tipodemedios = GetDataNN(_service, "gfa_catalogodemedios", "gfa_catalogodemediosid", new ColumnSet("gfa_catalogodemediosid"),
                                                            "gfa_promociones_gfa_catalogodemedios", "gfa_catalogodemediosid", "gfa_promocionesid", Promocion["gfa_promocionesid"].ToString());

                    arraymvtos = new string[Tipodemedios.Entities.Count()];
                    int cont = 0;
                    foreach (Entity reg in Tipodemedios.Entities)
                    {
                        arraymvtos[cont] = reg["gfa_catalogodemediosid"].ToString().ToUpper();
                        cont = cont + 1;
                    }

                    bool existe = Array.IndexOf(arraymvtos, _tipomedio.ToUpper()) >= 0;

                    if (!existe)
                        continue;
                    /***********************************************************************************/

                    #endregion

                    revisaganadores = ExisteAtributo("gfa_ganadores", Promocion) ? (bool)Promocion["gfa_ganadores"] : false;
                    numganadores = ExisteAtributo("gfa_numganadores", Promocion) ? (int)Promocion["gfa_numganadores"] : 0;
                    ganadoresactuales = ExisteAtributo("gfa_conteoganadoresactuales", Promocion) ? (int)Promocion["gfa_conteoganadoresactuales"] : 0;
                    bonokm = ExisteAtributo("gfa_bonokm", Promocion) ? (int)Promocion["gfa_bonokm"] : 0;
                    criteriocumple = ExisteAtributo("gfa_promocumple", Promocion) ? (bool)Promocion["gfa_promocumple"] : false;
                    criterioddmadre = ExisteAtributo("gfa_promodiadelasmadres", Promocion) ? (bool)Promocion["gfa_promodiadelasmadres"] : false;
                    criterioddpadre = ExisteAtributo("gfa_promodiadelpadre", Promocion) ? (bool)Promocion["gfa_promodiadelpadre"] : false;
                    criteriociudad = ExisteAtributo("gfa_activacriterio", Promocion) ? (bool)Promocion["gfa_activacriterio"] : false;
                    criterionumservicio = ExisteAtributo("gfa_activacriterionumser", Promocion) ? (bool)Promocion["gfa_activacriterionumser"] : false;
                    criterioorigendest = ExisteAtributo("gfa_activacriterioorigendest", Promocion) ? (bool)Promocion["gfa_activacriterioorigendest"] : false;
                    destinoid = ExisteAtributo("gfa_ciudadid", Promocion) ? ((EntityReference)Promocion["gfa_ciudadid"]).Id.ToString() : "";
                    origendestid = ExisteAtributo("gfa_origendestinoid", Promocion) ? ((EntityReference)Promocion["gfa_origendestinoid"]).Id.ToString() : "";
                    numeroservicio = ExisteAtributo("gfa_numerodeservicio", Promocion) ? Promocion["gfa_numerodeservicio"].ToString() : "";
                    vigenciaal = ExisteAtributo("gfa_vigenciaal", Promocion) ? ((DateTime)Promocion["gfa_vigenciaal"]).ToLocalTime() : DateTime.Now;
                    vigenciadel = ExisteAtributo("gfa_vigenciadel", Promocion) ? ((DateTime)Promocion["gfa_vigenciadel"]).ToLocalTime() : DateTime.Now;
                    // 3 Noviembre 2014 - Adecuación Cancelaciones
                    NombrePromo = ExisteAtributo("gfa_name", Promocion) ? (string)Promocion["gfa_name"] : string.Empty;


                    //"gfa_promodiadelpadre","gfa_promodiadelasmadres","gfa_promodiadelnino"

                    promocionid = Promocion["gfa_promocionesid"].ToString();
                    AsignarPromocion = true;

                    #region se revisa si no se le ha asignado con anterioridad esta promocion al cliente
                    
                    // 11 Diciembre 2014 - Si el movimiento no es Acumulacion - Aplica Verificar Ganadores
                    if (!_esmovacumulacion)
                    {
                        string[] ColumSet = new string[] { "gfa_extrakmid", "gfa_promocionid", "gfa_socioid" };
                        EntityCollection Ganadores = RecuperacionMultiple("gfa_extrakm", ColumSet, "gfa_promocionid", promocionid, "gfa_socioid", _socioid);

                        if (Ganadores.Entities.Count() > 0)
                        {
                            AsignarPromocion = false;
                            break; 
                        }
                    }
                    #endregion

                    #region Criterio Numero de Ganadores
                    if (revisaganadores)
                    {
                        if (ganadoresactuales >= numganadores)
                        {
                            AsignarPromocion = false;
                            continue;
                        }
                        else
                        {
                            ganadoresactuales = ganadoresactuales + 1;
                        }
                    }
                    #endregion

                    #region Criterio cumple

                    if (criteriocumple)
                    {
                        string cumple;
                        string hoycumple;

                        cumple = _Fechacumple.Month.ToString() + "/" + _Fechacumple.Day.ToString();
                        hoycumple = DateTime.Now.ToLocalTime().Month.ToString() + "/" + DateTime.Now.ToLocalTime().Day.ToString();

                        if (_Fechacumple == DateTime.MinValue)
                        {
                            AsignarPromocion = false;
                            continue;
                        }

                        if (cumple == hoycumple)
                        {
                            AsignarPromocion = true;
                        }
                        else
                        {
                            AsignarPromocion = false;
                            continue;
                        }
                    }
                    #endregion

                    #region Criterio dia de la madres

                    if (criterioddmadre)
                    {
                        if (genero == 2 & tienehijos)
                        {
                            AsignarPromocion = true;
                        }
                        else
                        {
                            AsignarPromocion = false;
                            continue;
                        }
                    }
                    #endregion

                    #region Criterio dia del padre

                    if (criterioddpadre)
                    {
                        if (genero == 1 & tienehijos)
                        {
                            AsignarPromocion = true;
                        }
                        else
                        {
                            AsignarPromocion = false;
                            continue;
                        }
                    }
                    #endregion

                    #region Criterio Ciudad

                    if (criteriociudad)
                    {
                        if (_ciudadid == destinoid)
                        {
                            AsignarPromocion = true;
                        }
                        else
                        {

                            if (cdmexico(_ciudadid) && cdmexico(destinoid))
                            {
                                AsignarPromocion = true;
                            }
                            else
                            {
                                AsignarPromocion = false;
                                continue;
                            }
                        }
                    }

                    #endregion

                    #region Criterio Origen Destino

                    if (criterioorigendest)
                    {
                        if (_OrigenDestinoid == origendestid)
                        {
                            AsignarPromocion = true;
                        }
                        else
                        {
                            AsignarPromocion = false;
                            continue;
                        }

                    }

                    #endregion

                    #region Criterio Numero de Servicio

                    if (criterionumservicio)
                    {
                        if (numeroservicio == _numerodeservicio)
                        {
                            AsignarPromocion = true;

                        }
                        else
                        {
                            AsignarPromocion = false;
                            continue;
                        }
                    }

                    #endregion

                    #region Asigna Promocion

                    if (AsignarPromocion)
                    {
                        Entity kmExtras = new Entity("gfa_extrakm");

                        kmExtras["gfa_promocionid"] = new EntityReference("gfa_promociones", new Guid(promocionid));

                        if (ClaveSocio.ToUpper() != "CO")
                            kmExtras["gfa_socioid"] = new EntityReference("contact", new Guid(Socioid));
                        else
                            kmExtras["gfa_empresaid"] = new EntityReference("account", new Guid(Socioid));

                        /*Mandamos la creación de Kilómetros Extra para liberarse */
                        kmExtras["gfa_kmextras"] = bonokm;
                        kmExtras["statuscode"] = new OptionSetValue(223060002);

                        kmExtras["gfa_kmpromocion"] = true;
                        kmExtras["gfa_motivo"] = "PUNTOS POR PROMOCION DE " + NombrePromo;
                        kmExtras["gfa_justificaciondemovimientoid"] = new EntityReference("gfa_justmov", new Guid(CveJustifica));
                        kmExtras["gfa_observaciones"] = "Registro de Promoción Generado de manera automática por Dynamics CRM.";

                        // 3 Nov 2014 - Regresamos Guid de Reg Creado
                        IdKmExtraProm = _service.Create(kmExtras);

                        if (revisaganadores)
                        {
                            Promocion["gfa_conteoganadoresactuales"] = ganadoresactuales;
                            _service.Update(Promocion);

                            if (ganadoresactuales == numganadores)
                            {
                                var req = new SetStateRequest()
                                {
                                    EntityMoniker = new EntityReference("gfa_promociones", new Guid(promocionid)),
                                    State = new OptionSetValue(1),
                                    Status = new OptionSetValue(2),
                                };

                                _service.Execute(req);
                            }
                        }
                    }

                    #endregion

                    break;
                }
                #endregion

            }
            catch (Exception ex)
            {
            }

            return IdKmExtraProm;
        }

        # region # Método Recupera Promoción por tiposocio, tipomedio, tipomovimiento
        private EntityCollection RevisaPromociones(string Entidad, string[] Columnas, DateTime fecha, string AtributoFiltro1, string ValorFiltro1, string AtributoFiltro2, string ValorFiltro2)
        {
            // Se especifica el nombre de la entidad de dónde se obtendrán los datos (FROM)
            QueryExpression consulta = new QueryExpression(Entidad);

            // Campos a recuperar de la tabla (SELECT)
            consulta.ColumnSet.AddColumns(Columnas);
            consulta.AddOrder("gfa_vigenciaal", OrderType.Ascending);
            consulta.AddOrder("gfa_vigenciadel", OrderType.Descending);

            // Filtro 1 y 2 como condición en la consulta (WHERE)
            consulta.Criteria = new FilterExpression();
            consulta.Criteria.AddCondition(AtributoFiltro1, ConditionOperator.Equal, new Guid(ValorFiltro1));

            FilterExpression filtrohijo = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition(AtributoFiltro2, ConditionOperator.Equal, new Guid(ValorFiltro2));

            //FilterExpression filtrosubhijo = consulta.Criteria.AddFilter(LogicalOperator.And);
            //filtrohijo.AddCondition(AtributoFiltro3, ConditionOperator.Equal, new Guid(ValorFiltro3));

            FilterExpression filtrofechaal = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition("gfa_vigenciaal", ConditionOperator.GreaterEqual, fecha.ToLocalTime());

            FilterExpression filtrofechadel = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition("gfa_vigenciadel", ConditionOperator.LessEqual, fecha.ToLocalTime());

            FilterExpression filtrostatecode = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition("statecode", ConditionOperator.Equal, 0);

            // Se guarda el resultado en una colección de datos
            EntityCollection Registros = _service.RetrieveMultiple(consulta);

            return Registros;

        }
        #endregion

        # region # Método Promociones Vigentes
        private EntityCollection RecuperaPromocionesVigentes(string Entidad, string[] Columnas, DateTime fecha)
        {
            // Se especifica el nombre de la entidad de dónde se obtendrán los datos (FROM)
            QueryExpression consulta = new QueryExpression(Entidad);

            // Campos a recuperar de la tabla (SELECT)
            consulta.ColumnSet.AddColumns(Columnas);

            // Filtro 1 y 2 como condición en la consulta (WHERE)
            consulta.Criteria = new FilterExpression();
            consulta.Criteria.AddCondition("gfa_vigenciadel", ConditionOperator.LessEqual, fecha.ToLocalTime());

            FilterExpression filtrohijo = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition("gfa_vigenciaal", ConditionOperator.GreaterEqual, fecha.ToLocalTime());

            FilterExpression filtrostatecode = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition("statecode", ConditionOperator.Equal, 0);

            // Se guarda el resultado en una colección de datos
            EntityCollection Registros = _service.RetrieveMultiple(consulta);

            return Registros;

        }
        #endregion

        # region # Método de Recuperación de datos en CRM 1 Filtro (Equal)
        private EntityCollection RecuperacionMultiple(string Entidad, string[] Columnas, string AtributoFiltro1, string ValorFiltro1)
        {
            // Se especifica el nombre de la entidad de dónde se obtendrán los datos (FROM)
            QueryExpression consulta = new QueryExpression(Entidad);

            // Campos a recuperar de la tabla (SELECT)
            consulta.ColumnSet.AddColumns(Columnas);

            // Filtro 1 y 2 como condición en la consulta (WHERE)
            consulta.Criteria = new FilterExpression();
            consulta.Criteria.AddCondition(AtributoFiltro1, ConditionOperator.Equal, ValorFiltro1);


            // Se guarda el resultado en una colección de datos
            EntityCollection Registros = _service.RetrieveMultiple(consulta);

            return Registros;

        }

        #endregion

        # region # Método de Recuperación de datos en CRM 2 filtros (AND) (Equal)
        private EntityCollection RecuperacionMultiple(string Entidad, string[] Columnas, string AtributoFiltro1, string ValorFiltro1, string AtributoFiltro2, string ValorFiltro2)
        {
            // Se especifica el nombre de la entidad de dónde se obtendrán los datos (FROM)
            QueryExpression consulta = new QueryExpression(Entidad);

            // Campos a recuperar de la tabla (SELECT)
            consulta.ColumnSet.AddColumns(Columnas);

            // Filtro 1 y 2 como condición en la consulta (WHERE)
            consulta.Criteria = new FilterExpression();
            consulta.Criteria.AddCondition(AtributoFiltro1, ConditionOperator.Like, ValorFiltro1);

            FilterExpression filtrohijo = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition(AtributoFiltro2, ConditionOperator.Equal, ValorFiltro2);

            //FilterExpression filtrostatecode = consulta.Criteria.AddFilter(LogicalOperator.And);
            //filtrohijo.AddCondition("statecode", ConditionOperator.NotEqual, 1);

            FilterExpression filtrostatuscode = consulta.Criteria.AddFilter(LogicalOperator.And);
            filtrohijo.AddCondition("statuscode", ConditionOperator.NotEqual, 223060001);


            // Se guarda el resultado en una colección de datos
            EntityCollection Registros = _service.RetrieveMultiple(consulta);

            return Registros;

        }
        #endregion

        #region # Método utilizado para conocer si el atributo se encuentra en el diccionario de datos
        static Boolean ExisteAtributo(string name, Entity entity)
        {
            Boolean existe = false;
            foreach (var EntidadRes in entity.Attributes)
            {
                if (EntidadRes.Key == name) { existe = true; }
            }
            return existe;
        }
        #endregion

        /// <summary>
        ///  Metodo que devuelve la descripcion de un optionsetvalue
        ///  de las tablas intermedias.
        /// </summary>
        /// Parámetros 
        /// <param name="Entidad">Nombre de la entidad de donde se encuentra el OptionSet.</param>   
        /// <param name="sNombreLogico">Nombre lógico del OptionSet.</param>  
        /// <param name="sValue">Código del catalogo correspondiente al OptionSet.</param>  
        /// <param name="Servicio">WS de la organización.</param>        

        private string CatalogoOptionSet(string Entidad, string sNombreLogico, string sValue, IOrganizationService Servicio)
        {
            string desValorCatalogo = "";
            #region Traer Descripcion de PickList en base al ID


            RetrieveAttributeRequest retrieveAttributeRequest = new RetrieveAttributeRequest
            {
                EntityLogicalName = Entidad,
                LogicalName = sNombreLogico,
                RetrieveAsIfPublished = true
            };

            // Ejecutar la peticion         
            RetrieveAttributeResponse retrieveAttributeResponse = (RetrieveAttributeResponse)Servicio.Execute(retrieveAttributeRequest);
            // Accesando a la información del PickList              
            PicklistAttributeMetadata retrievedPicklistAttributeMetadata = (PicklistAttributeMetadata)retrieveAttributeResponse.AttributeMetadata;
            OptionMetadata[] optionList = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray();

            foreach (OptionMetadata oMD in optionList)
            {
                try
                {
                    if (oMD.Value.Value.ToString() == sValue)
                    {
                        //IdValorCatalogo = oMD.Value.Value;
                        desValorCatalogo = oMD.Label.UserLocalizedLabel.Label.ToString();
                        break;
                    }
                }
                catch (Exception ex)
                {

                }
            }
            return desValorCatalogo;
            #endregion
        }

        /*Recupera si la ciudad es unos de los definidos como ciudad de mexico*/
        private bool cdmexico(string idciudad)
        {
            var columns = new[] { "new_ciudadid", "new_claveciudad" };
            Entity ciudad = _service.Retrieve("new_ciudad", new Guid(idciudad), new ColumnSet(columns));
            string clave = ExisteAtributo("new_claveciudad", ciudad) ? ciudad["new_claveciudad"].ToString() : "";

            string[] arr = { "0901", "0902", "0903", "0904", "0905", "0906", "0907", "0908", "0909", "0910", "0911", "0912", "0913", "0914", "0915", "0916" };

            bool existe = Array.IndexOf(arr, clave) >= 0;
            return existe;
        }

        #region Devuelve los valores de entidades relacionadas N:N
        /// <summary>
        ///  Devuelve los valores de entidades relacionadas N:N
        /// </summary>
        /// Parámetros 
        /// <param name="_service">WS de la organización</param> 
        /// <param name="Entidad1">Primera Entidad de la Relacion</param>   
        /// <param name="Columnid_entidad1">Columna id de la Primera entidad de la relación</param>                         
        /// <param name="Obtener_Columns">Columnas que se desean recuperar de la primera entidad</param>
        /// <param name="EntidadRel">Entidad Relacionada</param>
        /// <param name="Columnid_entidadrel">Columna con la que se relacionara la entidad relacionada</param>
        /// <param name="filtercol">Columna id de la entidad Relacionada</param>
        /// <param name="Guid">Valor que se le asignara al filtro</param>
        public EntityCollection GetDataNN(IOrganizationService _service, string Entidad1, string Columnid_entidad1,
                                          ColumnSet Obtener_Columns, string EntidadRel, string Columnid_entidadrel,
                                          string filtercol, string Guid)
        {
            Guid id = new Guid(Guid); //
            //Creando Query Expression.
            QueryExpression query = new QueryExpression()
            {
                EntityName = Entidad1,//"contact",
                ColumnSet = Obtener_Columns,//new ColumnSet("contactid"),
                LinkEntities = 
                {
                    new LinkEntity 
                    {
                        LinkFromEntityName = Entidad1,//"contact",
                        LinkFromAttributeName = Columnid_entidad1,//"contactid",
                        LinkToEntityName = EntidadRel,//"contactinvoices",                              
                        LinkToAttributeName = Columnid_entidadrel,//"contactid",
                        LinkCriteria = new FilterExpression
                        {
                            FilterOperator = LogicalOperator.And,
                            Conditions = 
                            {
                                new ConditionExpression 
                                {
                                    AttributeName = filtercol, //"invoiceid",
                                    Operator = ConditionOperator.Equal,
                                    Values = { id }
                                }
                            }
                        }
                    }
                }
            };
            // Obtener los resultados 
            EntityCollection ec = _service.RetrieveMultiple(query);
            return ec;
        }
        #endregion

    }
}
